<?php
// +----------------------------------------------------------------------
// | [KyPHP System] Copyright (c) 2020 http://www.kuryun.com/
// +----------------------------------------------------------------------
// | [KyPHP] 并不是自由软件,你可免费使用,未经许可不能去掉KyPHP相关版权
// +----------------------------------------------------------------------
// | Author: fudaoji <fdj@kuryun.cn>
// +----------------------------------------------------------------------

/**
 * Created by PhpStorm.
 * Script Name: App.php
 * Create: 2020/5/17 下午5:08
 * Description: 应用中心
 * Author: fudaoji<fdj@kuryun.cn>
 */

namespace app\admin\controller;

use app\common\model\AdminStore;
use think\facade\Log;

class App extends Base
{
    /**
     * @var \app\common\model\Addons
     */
    private $addonM;
    /**
     * @var \app\common\model\AddonsInfo
     */
    private $addonInfoM;
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->addonM = model('addons');
        $this->addonInfoM = model('addonsInfo');
    }

    /**
     * 为小程序应用设置模版
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function setTemplate(){
        if(request()->isPost()){
            $post_data = input('post.');
            $mini_template = model('addonsTemplate')->getOneByMap(['addon' => $post_data['addon']], true, true);
            if($mini_template){
                $res = model('addonsTemplate')->updateOne(['id' => $mini_template['id'], 'template_id' => $post_data['template_id']]);
            }else{
                $res = model('addonsTemplate')->addOne(['addon' => $post_data['addon'], 'template_id' => $post_data['template_id']]);
            }
            if($res){
                $this->success('设置成功', url('index', ['type' => 'onsale']));
            }else{
                $this->error('系统出错，请刷新重试','', ['token' => request()->token()]);
            }
        }
        if(! $data = $this->addonM->getOne(input('id', 0, 'intval'))){
            $this->error('请先安装此应用');
        }
        $mini_template = model('addonsTemplate')->getOneByMap(['addon' => $data['addon']], true, true);
        if(! $mini_template){
            $mini_template = ['addon' => $data['addon']];
        }
        $mini_template['addon_name'] = $data['name'];
        $templates = model('miniTemplate')->getField('template_id, user_desc', ['type' => \app\common\model\MiniTemplate::TEMPLATE], true);
        $builder = new FormBuilder();
        $builder->addFormItem('addon', 'hidden', 'addon', 'addon')
            ->addFormItem('addon_name', 'static', '应用','应用')
            ->addFormItem('template_id', 'chosen', '选择模版', '选择模版', $templates, 'required')
            ->setFormData($mini_template);
        return $builder->show();
    }

    /**
     * 卸载应用
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function uninstall()
    {
        if (request()->isPost()) {
            $name = input('name', '');
            if ($name == '') {
                $this->error('没有要卸载的应用');
            }
            $path= ADDON_PATH . $name . DS;
            if(!file_exists($path)){
                $this->error($path.'目录不存在');
            }
            if(!is_writable($path)){
                $this->error($path.'目录没有删除权限');
            }

            controller('common/addon', 'event')->clearAddonData(['name' => $name]); //再次清空数据
            if(del_dir_recursively($path)){
                $this->success('应用卸载成功，数据及文件都已删除');
            }else{
                $this->error('删除应用目录失败');
            }
        }
    }

    /**
     * 应用还原
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function wipeData()
    {
        if (request()->isPost()) {
            $name = input('name', '');
            if ($name == '') {
                $this->error('没有要还原的应用');
            }
            $res = controller('common/addon', 'event')->clearAddonData(['name' => $name]);
            if($res === true){
                $this->success('应用还原成功');
            }else{
                $this->error('还原失败，失败原因请查看日志');
            }
        }
    }

    /**
     * 安装/启用应用扩展
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function install()
    {
        if (request()->isPost()) {
            $name = input('name', '');
            if ($name == '') {
                $this->error('name参数错误');
            }
            cache('callAddonCache'.$name, null);

            if ($addon = $this->addonM->getOneByMap(['addon' => $name], true, true)) {
                if ($addon['status'] == 1) {
                    $this->error('应用已安装，请先卸载再重新安装');
                } else {
                    //小程序应用必须关联了模版，才能上架
                    if($addon['type'] == AdminStore::MINI && ! model('addonsTemplate')->total(['addon' => $name], true)){
                        $this->error('请先为此应用设置模版', url('setTemplate', ['id' => $addon['id']]));
                    }
                    $this->addonM->updateOne(['id' => $addon['id'], 'status' => 1]);
                    $this->success('应用上架成功', url('index', ['type'=>'onsale']));
                }
            } else {
                $cf = $this->addonM->getAddonConfigByFile($name);
                $data = [
                    'name' => isset($cf['name']) ? $cf['name'] : '',
                    'addon' => isset($cf['addon']) ? $cf['addon'] : '',
                    'desc' => isset($cf['desc']) ? $cf['desc'] : '',
                    'version' => isset($cf['version']) ? $cf['version'] : '',
                    'author' => isset($cf['author']) ? $cf['author'] : '',
                    'logo' => isset($cf['logo']) ? ('/addons/' . $cf['addon'] . '/'.$cf['logo']) : '',
                    'menu_show' => isset($cf['menu_show']) ? $cf['menu_show'] : '1',
                    'entry_url' => isset($cf['entry_url']) ? $cf['entry_url'] : '',
                    'admin_url' => isset($cf['admin_url']) ? $cf['admin_url'] : '',
                    'config' => isset($cf['config']) ? json_encode($cf['config']) : '',
                    'status' => 0,
                    'type' => isset($cf['type']) ? $cf['type'] : AdminStore::MP,
                ];

                $result = $this->validate($data, 'Addon');

                if ($result !== true) {
                    $this->error($result);
                }

                if (isset($cf['install_sql']) && $cf['install_sql'] != '') {
                    $install_file = ADDON_PATH . $name . DS . $cf['install_sql'];
                    if (!is_file($install_file)) {
                        $this->error('没有找到安装数据的SQL文件：' . $cf['install_sql']);
                    } else {
                        if (!strpos($install_file, '.sql')) {
                            $this->error('安装文件格式有误');
                        }
                        $res = execute_addon_install_sql($install_file);
                        if($res !== true){
                            $this->error($res);
                        }
                    }
                }
                if ($addon = $this->addonM->addOne($data)) {
                    $insert = ['id' => $addon['id']];
                    $remote_info = $this->fetchApp('groupcode');
                    if($remote_info !== false){
                        $insert['detail'] = empty($remote_info['data']['info']['detail']) ? '' : $remote_info['data']['info']['detail'];
                        $insert['cates'] = empty($remote_info['data']['info']['cates']) ? '' : $remote_info['data']['info']['cates'];
                        $insert['snapshot'] = empty($remote_info['data']['info']['snapshot']) ? '' : $remote_info['data']['info']['snapshot'];
                    }
                    $this->addonInfoM->addOne($insert);
                    $extra_msg = $data['type'] == AdminStore::MINI ? ',您需要为此应用设置模版才可以正式上架' : '';
                    $this->success('安装应用成功' . $extra_msg, url('index', ['type'=>'notinstall']));
                }else{
                    $this->error('安装应用失败');
                }
            }
        }
    }

    /**
     * 下架
     * @throws \think\Exception
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function close()
    {
        if (request()->isPost()) {
            $name = input('name', '');
            $addon = $this->addonM->getOneByMap(['addon' => $name, 'status' => 1], true, true);
            if (empty($addon)) {
                $this->error('没有要停用的应用');
            }
            cache('callAddonCache'.$name, null);

            if ($this->addonM->updateOne(['status' => 0, 'id' => $addon['id']])) {
                $this->success('停用应用成功');
            }
            $this->error('停用应用失败');
        }
    }


    /**
     * 应用中心
     * @param string $type
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function index($type = 'uninstall')
    {
        $search_key = input('search_key', '');
        $app_type = input('app_type', 'all');
        $where = ['a.status' => 1];
        $type == 'onsale' && $where['a.status'] = 0;
        $search_key && $where['name'] = ['like', '%'.$search_key.'%'];
        $app_type !== 'all' && $where['type'] = $app_type;
        $apps = $this->addonM->pageJoin([
            'alias' => 'a',
            'join' => [
                ['addons_info ai', 'ai.id=a.id'],
                ['addons_template at', 'at.addon=a.addon', 'left']
            ],
            'page_size' => $this->pageSize,
            'where' => $where,
            'order' => ['ai.sale_num' => 'desc'],
            'field' => 'a.*,ai.sale_num,ai.price,at.template_id',
            'refresh' => 1
        ]);
        $page = $apps->appends([
            'search_key' => $search_key,
            'app_type' => $app_type,
            'type' => $type])->render();

        $addon_list = $apps;

        if ($type == 'notinstall') { //未安装
            $addon_folder = opendir(ADDON_PATH);
            $addons = []; //存放未安装的插件
            if ($addon_folder) {
                while (($file = readdir($addon_folder)) !== false) {
                    if ($file != '.' && $file != '..') {
                        if ($addon_local = $this->addonM->getAddonConfigByFile($file)) {
                            $addon_db = $this->addonM->getOneByMap(['addon' => $file], true, 1);
                            if (empty($addon_db)) {
                                $addons[] = $addon_local;
                            }
                        }
                    }
                }
            }
            $addon_list = $addons;
        }

        foreach ($addon_list as $key => $value) {
            if($type == 'notinstall'){
                $addon_list[$key]['logo'] = '/addons/'.$value['addon'].'/' . $value['logo'];
            }
        }

        $assign = [
            'addons' => $addon_list,
            'apps' => $apps,
            'type' => $type,
            'app_type' => $app_type,
            'search_key' => $search_key,
            'page' => $page
        ];
        return $this->show($assign);
    }

    /**
     * 编辑应用信息
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function edit(){
        if(request()->isPost()){
            $post_data = input('post.');
            unset($post_data['__token__']);
            $this->addonInfoM->updateOne($post_data);
            $this->success('保存成功', url('index'));
        }
        if(! $data = $this->addonM->getOne(input('id', 0, 'intval'))){
            $this->error('数据不存在');
        }

        $data = array_merge($data, $this->addonInfoM->getOne($data['id']));
        $data['cates'] = empty($data['cates']) ? [] : explode(',', $data['cates']);

        $cates = array_values(model('addonsCate')->getField('title', ['status' => 1], true));

        $builder = new FormBuilder();
        $builder->addFormItem('id', 'hidden', 'id', 'id')
            ->addFormItem('cates', 'chosen_multi', '分类标签', '可多选', array_combine($cates, $cates), 'required')
            ->addFormItem('sale_num_show', 'number', '虚拟销量', '前台显示的数字', [], 'required min=0')
            ->addFormItem('old_price', 'text', '原价', '原价', [], 'required min="0"')
            ->addFormItem('price', 'text', '售价', '每年的费用', [], 'required min="0"')
            ->addFormItem('snapshot', 'pictures_url', '应用快照', '应用典型界面截图', [], 'required')
            ->addFormItem('detail', 'ueditor', '详细介绍', '详细介绍', [], 'required max=50000')
            ->setFormData($data);

        return $builder->show();
    }

    /**
     * 从官方市场获取应用详情
     * @param int $name
     * @return mixed
     * Author: fudaoji<fdj@kuryun.cn>
     */
    protected function fetchApp($name = ''){
        $request = new \GuzzleHttp\Psr7\Request('post', 'app/getByNamePost');
        $client = new \GuzzleHttp\Client(['base_uri' => 'https://kyphp.kuryun.com/api/']);
        try {
            $res = $client->send($request, [
                'json' => ['name' => $name]
            ]);
            if($res->getStatusCode() == 200){
                return json_decode($res->getBody()->getContents(), true);
            }
        }catch (\Exception $e){
            Log::error($e->getMessage());
        }
        return false;
    }
}